useWork 方法封装
将 SharedWorker 的连接、消息收发逻辑封装为 Vue Composable,便于在组件中复用。
封装目标
- 自动管理 Worker 连接生命周期
- 提供简洁的消息收发 API
- 支持消息类型过滤
- 组件卸载时自动清理连接
实现代码
// composables/useSharedWorker.ts
import { ref, onUnmounted } from 'vue'
interface WorkerMessage {
type: string
data?: any
from?: string
clientId?: string
}
export function useSharedWorker(workerUrl: string) {
const worker = ref<SharedWorker | null>(null)
const clientId = ref<string>('')
const messages = ref<WorkerMessage[]>([])
const connected = ref(false)
function connect() {
worker.value = new SharedWorker(workerUrl)
const port = worker.value.port
port.start()
connected.value = true
port.onmessage = (event: MessageEvent<WorkerMessage>) => {
const message = event.data
if (message.type === 'connected') {
clientId.value = message.clientId!
return
}
messages.value.push(message)
}
}
function send(type: string, data?: any) {
if (!worker.value) return
worker.value.port.postMessage({ type, data })
}
function broadcast(data: any) {
send('broadcast', data)
}
function sendTo(targetId: string, data: any) {
send('direct', { targetId, data })
}
function disconnect() {
if (worker.value) {
worker.value.port.close()
worker.value = null
connected.value = false
}
}
onUnmounted(() => {
disconnect()
})
return {
clientId,
messages,
connected,
connect,
send,
broadcast,
sendTo,
disconnect
}
}
typescript
使用方式
<script setup>
const { clientId, messages, connected, connect, broadcast } = useSharedWorker('/worker.js')
onMounted(() => {
connect()
})
function handleSend() {
broadcast({ text: 'Hello from tab', from: clientId.value })
}
</script>
vue
设计要点
- 使用
ref包装状态,确保响应式 messages数组自动累积,组件可 watch 它来处理新消息onUnmounted自动清理,避免连接泄漏- 支持
broadcast(广播)和sendTo(定向)两种发送模式
↑